package com.yungu.swift.admin.route.operation;

import com.alibaba.dubbo.config.annotation.Reference;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.yungu.swift.admin.thread.OrderTodayThread;
import com.yungu.swift.assets.driver.model.param.AdminDriverAroundParam;
import com.yungu.swift.assets.driver.model.param.AdminDriverMonitorParam;
import com.yungu.swift.assets.driver.model.vo.AdminDriverMonitorVo;
import com.yungu.swift.assets.driver.model.vo.AdminMonitorDriverDetailVo;
import com.yungu.swift.assets.driver.model.vo.AdminMonitorDriverStatusVo;
import com.yungu.swift.assets.driver.model.vo.DriverVo;
import com.yungu.swift.assets.driver.service.DriverMonitorService;
import com.yungu.swift.assets.driver.service.DriverService;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.model.PageVo;
import com.yungu.swift.base.model.admin.AdminParam;
import com.yungu.swift.lbs.model.BusinessPoint;
import com.yungu.swift.lbs.model.DriverPoint;
import com.yungu.swift.lbs.service.LocationService;
import com.yungu.swift.order.model.param.AdminMapTodayOrderPageParam;
import com.yungu.swift.order.model.vo.AdminMapTodayOrderVo;
import com.yungu.swift.order.service.OrderAdminService;
import com.yungu.swift.order.service.OrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author : cuixiuyin
 * @date : 2019/7/2
 */
@Slf4j
@RestController
@RequestMapping("/admin/v1/operation/monitor")
@Api(value = "【运营管理】", tags = "监控地图")
public class MonitoringMapAdmin {

    @Autowired
    private RedisCacheService redisCacheService;
    @Reference
    private DriverMonitorService driverMonitorService;
    @Reference
    private LocationService locationService;
    @Reference
    private OrderService orderService;
    @Reference
    private OrderAdminService orderAdminService;
    @Reference
    private DriverService driverService;

    public static final int THREAD_SIZE = Runtime.getRuntime().availableProcessors() + 1;

    private ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("monitoring-map-pool-%d").build();
    private ExecutorService executor = new ThreadPoolExecutor(THREAD_SIZE, 100, 0L,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

    @RequestMapping(value = "/driverList", method = {RequestMethod.POST})
    @ApiOperation(value = "监控地图今日司机", httpMethod = "POST")
    public ResponseData<AdminDriverMonitorVo> driverList(@RequestBody AdminDriverMonitorParam monitorParam) {
        return driverMonitorService.getDriverList(monitorParam);
    }

    @RequestMapping(value = "/todayOrderList", method = {RequestMethod.POST})
    @ApiOperation(value = "监控地图今日订单", httpMethod = "POST")
    public ResponseData<PageVo<AdminMapTodayOrderVo>> todayOrderList(@RequestBody AdminMapTodayOrderPageParam pageParam) throws InterruptedException {
        ResponseData<PageVo<AdminMapTodayOrderVo>> responseData = orderAdminService.orderTodayList(pageParam);
        if (responseData.isSuccess() && responseData.getData() != null && responseData.getData().getItems() != null) {
            List<AdminMapTodayOrderVo> items = responseData.getData().getItems();
            CountDownLatch countDownLatch = new CountDownLatch(items.size());
            items.forEach(adminMapTodayOrderVo ->
                    executor.execute(new OrderTodayThread(redisCacheService, locationService, adminMapTodayOrderVo, countDownLatch))
            );
            // 接口超时时间 10s，8秒没执行完，直接返回
            countDownLatch.await(8, TimeUnit.SECONDS);
        }
        return responseData;
    }


    @RequestMapping(value = "/getDriverDetail", method = {RequestMethod.GET})
    @ApiOperation(value = "司机在线情况和营收情况", httpMethod = "GET")
    public ResponseData<AdminMonitorDriverDetailVo> getDriverDetail(@RequestParam String driverUuid) {
        return driverMonitorService.getMonitorDriverDetail(driverUuid);
    }


    @RequestMapping(value = "/getDriverStatus", method = {RequestMethod.GET})
    @ApiOperation(value = "司机今日全状态", httpMethod = "GET")
    public ResponseData<List<AdminMonitorDriverStatusVo>> getDriverStatus(@RequestParam String driverUuid,
                                                                          @RequestBody AdminParam adminParam) {
        return driverMonitorService.getMonitorDriverStatus(driverUuid, adminParam.getAppid());
    }

    @RequestMapping(value = "/getOrderDetail", method = {RequestMethod.GET})
    @ApiOperation(value = "所选订单详情", httpMethod = "GET")
    public ResponseData<AdminMapTodayOrderVo> getOrderDetail(@RequestParam String orderUuid) {
        ResponseData<AdminMapTodayOrderVo> responseData = orderAdminService.mapOrderDetail(orderUuid);
        if (responseData.isSuccess() && responseData.getData() != null) {
            AdminMapTodayOrderVo mapTodayOrderVo = responseData.getData();
            CountDownLatch countDownLatch = new CountDownLatch(1);
            executor.execute(new OrderTodayThread(redisCacheService, locationService, mapTodayOrderVo, countDownLatch));
            countDownLatch.countDown();
        }
        return responseData;
    }

    @RequestMapping(value = {"/map/around"}, method = {RequestMethod.POST})
    @ApiOperation(value = "获取周围司机", response = ResponseData.class, notes = "list")
    public ResponseData<List<BusinessPoint>> map(@Valid @RequestBody AdminDriverAroundParam driverAroundParam) {
        List<DriverPoint> driverPoints = locationService.geoNearOnline(driverAroundParam.getType(),
                driverAroundParam.getLng(), driverAroundParam.getLat(), driverAroundParam.getAppid(),
                8000, 100).getData();
        if (CollectionUtils.isNotEmpty(driverPoints)) {
            List<String> driverUuids = driverPoints.stream().parallel().map(driverPoint -> driverPoint.getDriverUuid())
                    .distinct().collect(Collectors.toList());
            log.info("lng：{}, lat：{} 的司机列表：{}", driverAroundParam.getLng(), driverAroundParam.getLat(), driverUuids);
            //过滤上班状态司机
            List<String> workDriverUuids = driverService.filterWorkUuid(driverUuids).getData();
            if (CollectionUtils.isNotEmpty(workDriverUuids)) {
                driverPoints = driverPoints.stream().parallel().filter(driverPoint ->
                        workDriverUuids.contains(driverPoint.getDriverUuid())).collect(Collectors.toList());
            }
            if (CollectionUtils.isEmpty(driverPoints)) {
                log.warn("lng：{}, lat：{} 无符合业务司机", driverAroundParam.getLng(), driverAroundParam.getLat());
                return ResponseData.buildSuccessResponse("获取成功", Lists.newArrayList());
            }
            // 补充定位点位置信息
            List<BusinessPoint> businessPoints = driverPoints.stream().parallel().map(driverPoint -> {
                BusinessPoint businessPoint = new BusinessPoint();
                BeanUtils.copyProperties(driverPoint, businessPoint);
                ResponseData<DriverVo> driverVoResponseData = driverService.selInfo(businessPoint.getDriverUuid());
                if (driverVoResponseData.isSuccess() && driverVoResponseData.getData() != null) {
                    DriverVo driverVo = driverVoResponseData.getData();
                    businessPoint.setCarUuid(driverVo.getCarUuid());
                    businessPoint.setPlateNum(driverVo.getPlateNum());
                    businessPoint.setDriverMobile(driverVo.getMobile());
                    businessPoint.setDriverName(driverVo.getName());
                }
                return businessPoint;
            }).collect(Collectors.toList());
            return ResponseData.buildSuccessResponse("获取成功", businessPoints);
        }
        log.warn("lng：{}, lat：{} 附近找不到相关司机", driverAroundParam.getLng(), driverAroundParam.getLat());
        return ResponseData.buildSuccessResponse("获取成功", Lists.newArrayList());
    }


}
